package com.xinyue.ext.sql;

import java.io.PrintWriter;
import java.util.List;

import com.xinyue.ext.EnumData;
import com.xinyue.ext.data.EntityData;
import com.xinyue.ext.data.FieldData;
import com.xinyue.ext.util.StringUtil;

public class MySqlDB extends SqlContext implements EnumData{
	//私有构造器
	private MySqlDB() {
	}
	//内部类
	private static class SingletonHolder{
        private static MySqlDB instance = new MySqlDB();  
    }
	/**
	 * 获得对象实例
	 */
	public static MySqlDB getInstance(EntityData entity) {
		SqlContext.entity = entity;
		return SingletonHolder.instance;
	}


	/**
	 * 创建符合MySQL规范的sql语句
	 */
	@Override
	public void createSql(PrintWriter pw) {

		//建表语句
		pw.println("drop table if exists " + entity.getTable() + ";");
		pw.println("create table " + entity.getTable() + "(");
		
		//id
		FieldData id = entity.getId();
		
		if(id.isAuto_key()) {
			pw.println("\t" + buildField(id) + " auto_increment,");
		}else {
			pw.println("\t" + buildField(id) + ",");
		}
		
		//many-many字段
		List<FieldData> join = entity.getJoins();
		if(join != null && join.size() > 0) {
			for (int i = 0; i < join.size(); i++) {
				String sql = buildField(join.get(i));
				if(sql != null) {
					pw.println("\t" + sql + ",");
				}
			}
		}
		
		//字段
		List<FieldData> fd = entity.getFields();
		if(fd != null && fd.size() > 0) {
			for (int i = 0; i < fd.size(); i++) {
				String sql = buildField(fd.get(i));
				if(sql != null) {
					pw.println("\t" + sql + ",");
				}
			}
		}
		
		//主键和结尾
		if(StringUtil.isNull(id.getDbName())) {
			pw.println("\t" + "primary key(" + id.getName() + ")");
		}else {
			pw.println("\t" + "primary key(" + id.getDbName() + ")");
		}
		
		if(StringUtil.isNull(entity.getStart())) {
			pw.println(");");
		}else {
			pw.println(")AUTO_INCREMENT=" + entity.getStart() + ";");
		}
		pw.println();
	}
	
	/**
	 * 构建符合mySql规范的sql语句
	 * @return
	 */
	private String buildField(FieldData fd) {
		//瞬时字段无需定义
		if(fd.isAnn_transient()) {
			return null;
		}
		
		String flag = null;
		
		String type = fd.getType();
		String dbName = fd.getDbName();
		String len = fd.getLength();
		boolean notNull = fd.isNullable();
		boolean unique = fd.isUnique();
		
		//自定义类型则直接返回
		String def = fd.getDefinition();
		if(!StringUtil.isNull(def)) {
			if(!StringUtil.isNull(dbName)) {
				return dbName + " " + def;
			}
			return def + fd.getDbName();
		}
		
		//标准数据库字段类型
		if(javaType[0].equals(type)) {//Data
			if(notNull) {
				flag = mySQLType[0] + " not null";
			}else {
				flag = mySQLType[0];
			}
		}else if(javaType[1].equals(type)) {//BigDecimal
			flag = mySQLType[1] + "(19,2)";
		}else if(javaType[2].equals(type)) {//Blob
			flag = mySQLType[2];
		}else if(javaType[3].equals(type)) {//String
			if(StringUtil.isNull(len)) {
				flag = mySQLType[3] + "(255)";
			}else {
				flag = mySQLType[3] + "(" + len + ")";
			}
			//为空判断
			if(notNull) {
				flag += " not null";
			}
		}else if(javaType[4].equals(type)) {//boolean
			flag = mySQLType[4] + " not null";
		}else if(javaType[5].equals(type)) {//int
			if(StringUtil.isNull(len)) {
				flag = mySQLType[5] + " not null";
			}else {
				flag = mySQLType[5] + "(" + len + ")" + " not null";
			}
		}else if(javaType[6].equals(type)) {//double
			flag = mySQLType[6] + " not null";
		}else if(javaType[7].equals(type)) {//long
			if(StringUtil.isNull(len)) {
				flag = mySQLType[7] + " not null";
			}else {
				flag = mySQLType[7] + "(" + len + ")" + " not null";
			}
		}else if(javaType[8].equals(type)) {//float
			flag = mySQLType[8] + " not null";
		}else if(javaType[9].equals(type)) {//byte
			flag = mySQLType[9] + " not null";
		}else if(javaType[10].equals(type)) {//short
			flag = mySQLType[10] + " not null";
		}else if(javaType[11].equals(type)) {//char
			flag = mySQLType[11] + "(1) not null";
		}
		
		if(unique) {
			if(!StringUtil.isNull(dbName)) {
				return dbName + " " + flag + " unique";
			}
			return fd.getName() + " " + flag + " unique";
		}
		
		if(!StringUtil.isNull(dbName)) {
			return dbName + " " + flag;
		}
		return fd.getName() + " " + flag;
	}
}
